package org.urey.fmp.producer.processor;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
import org.urey.fmp.commom.annotation.CustomRequestBody;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

public class CustomMessageConverterMethodArgumentResolver extends RequestResponseBodyMethodProcessor {

	private final static String CUSTOM_REQUEST_BODY_KEY = "CUSTOM_REQUEST_BODY_KEY";

	protected final Logger logger = LoggerFactory.getLogger(getClass());

	protected final static Charset CHARSET = Charset.forName("UTF-8");

	public CustomMessageConverterMethodArgumentResolver(List<HttpMessageConverter<?>> converters) {
		super(converters);
	}

	@Override
	public boolean supportsParameter(MethodParameter parameter) {
		return parameter.hasParameterAnnotation(CustomRequestBody.class);
	}

	@Override
	protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType) throws IOException, HttpMediaTypeNotSupportedException, HttpMessageNotReadableException {
		CustomRequestBody parameterAnnotation = parameter.getParameterAnnotation(CustomRequestBody.class);

		String value = parameterAnnotation.value();
		if (StringUtils.isBlank(value)) {
			value = parameter.getExecutable().getParameters()[parameter.getParameterIndex()].getName();
		}

		ServletServerHttpRequest httpRequest = (ServletServerHttpRequest) inputMessage;

		String body = (String) httpRequest.getServletRequest().getAttribute(CUSTOM_REQUEST_BODY_KEY);
		if (body == null) {
			InputStream inputStream = inputMessage.getBody();
			body = IOUtils.toString(inputStream, Charset.forName("UTF-8"));
			body = URLDecoder.decode(body, CHARSET);
			httpRequest.getServletRequest().setAttribute(CUSTOM_REQUEST_BODY_KEY, body);
			logger.info("custom message read body:{}", body);
		}

		if (StringUtils.isBlank(body)) {
			return super.readWithMessageConverters(inputMessage, parameter, targetType);
		}

		JSONObject json = JSON.parseObject(body);
		String string = json.getString(value);

		logger.info("custom message converter json {}, key: {},value: {}", json, value, string);

		CustomHttpServletRequestWrapper customHttpServletRequestWrapper = new CustomHttpServletRequestWrapper(httpRequest.getServletRequest(), string);
		ServletServerHttpRequest serverHttpRequest = new ServletServerHttpRequest(customHttpServletRequestWrapper);

		return super.readWithMessageConverters(serverHttpRequest, parameter, targetType);
	}

}
